package com.example.blog.modules.user.service.impl;

import com.example.blog.common.exception.ServiceException;
import com.example.blog.modules.user.dto.RoleDTO;
import com.example.blog.modules.user.entity.Role;
import com.example.blog.modules.user.entity.User;
import com.example.blog.modules.user.repository.RoleRepository;
import com.example.blog.modules.user.repository.UserRepository;
import com.example.blog.modules.user.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {
    
    private final RoleRepository roleRepository;
    private final UserRepository userRepository;
    
    @Override
    @Transactional
    public RoleDTO createRole(RoleDTO roleDTO) {
        if (roleRepository.existsByName(roleDTO.getName())) {
            throw new ServiceException("角色名称已存在");
        }
        
        Role role = new Role();
        role.setName(roleDTO.getName());
        role.setDescription(roleDTO.getDescription());
        role.setPermissions(roleDTO.getPermissions());
        
        return convertToDTO(roleRepository.save(role));
    }
    
    @Override
    @Transactional
    public RoleDTO updateRole(Long id, RoleDTO roleDTO) {
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> new ServiceException("角色不存在"));
        
        if (!role.getName().equals(roleDTO.getName()) && roleRepository.existsByName(roleDTO.getName())) {
            throw new ServiceException("角色名称已存在");
        }
        
        role.setName(roleDTO.getName());
        role.setDescription(roleDTO.getDescription());
        role.setPermissions(roleDTO.getPermissions());
        
        return convertToDTO(roleRepository.save(role));
    }
    
    @Override
    @Transactional
    public void deleteRole(Long id) {
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> new ServiceException("角色不存在"));
        
        // 删除角色前先解除与用户的关联
        role.getUsers().forEach(user -> user.getRoleSet().remove(role));
        roleRepository.delete(role);
    }
    
    @Override
    public RoleDTO getRoleById(Long id) {
        return convertToDTO(roleRepository.findById(id)
                .orElseThrow(() -> new ServiceException("角色不存在")));
    }
    
    @Override
    public RoleDTO getRoleByName(String name) {
        return convertToDTO(roleRepository.findByName(name)
                .orElseThrow(() -> new ServiceException("角色不存在")));
    }
    
    @Override
    public List<RoleDTO> getAllRoles() {
        return roleRepository.findAll().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional
    public void assignRolesToUser(Long userId, Set<String> roleNames) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ServiceException("用户不存在"));
        
        Set<Role> roles = roleNames.stream()
                .map(name -> roleRepository.findByName(name)
                        .orElseThrow(() -> new ServiceException("角色不存在：" + name)))
                .collect(Collectors.toSet());
        
        user.getRoleSet().addAll(roles);
        userRepository.save(user);
    }
    
    @Override
    @Transactional
    public void removeRolesFromUser(Long userId, Set<String> roleNames) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ServiceException("用户不存在"));
        
        Set<Role> roles = roleNames.stream()
                .map(name -> roleRepository.findByName(name)
                        .orElseThrow(() -> new ServiceException("角色不存在：" + name)))
                .collect(Collectors.toSet());
        
        user.getRoleSet().removeAll(roles);
        userRepository.save(user);
    }
    
    @Override
    public Set<String> getUserRoles(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ServiceException("用户不存在"));
        
        return user.getRoleSet().stream()
                .map(Role::getName)
                .collect(Collectors.toSet());
    }
    
    @Override
    public Set<String> getUserPermissions(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ServiceException("用户不存在"));
        
        return user.getRoleSet().stream()
                .flatMap(role -> role.getPermissions().stream())
                .collect(Collectors.toSet());
    }
    
    private RoleDTO convertToDTO(Role role) {
        RoleDTO dto = new RoleDTO();
        dto.setId(role.getId());
        dto.setName(role.getName());
        dto.setDescription(role.getDescription());
        dto.setPermissions(role.getPermissions());
        return dto;
    }
} 